<template>
  <view class="tui-cascade-selection">
    <scroll-view
      scroll-x
      scroll-with-animation
      :scroll-into-view="scrollViewId"
      :style="{ backgroundColor: headerBgColor }"
      class="tui-bottom-line"
      :class="{ 'tui-btm-none': !headerLine }"
    >
      <view
        class="tui-selection-header"
        :style="{ height: tabsHeight, backgroundColor: backgroundColor }"
      >
        <view
          class="tui-header-item"
          :class="{ 'tui-font-bold': idx === currentTab && bold }"
          :style="{ color: idx === currentTab ? activeColor : color, fontSize: size + 'rpx' }"
          :id="`id_${idx}`"
          @tap.stop="swichNav"
          :data-current="idx"
          v-for="(item, idx) in selectedArr"
          :key="idx"
        >
          {{ item.text }}
          <view
            class="tui-active-line"
            :style="{ backgroundColor: lineColor }"
            v-if="idx === currentTab && showLine"
          ></view>
        </view>
      </view>
    </scroll-view>
    <swiper
      class="tui-selection-list"
      :current="currentTab"
      duration="300"
      @change="switchTab"
      :style="{ height: height, backgroundColor: backgroundColor }"
    >
      <swiper-item v-for="(item, index) in selectedArr" :key="index">
        <scroll-view
          scroll-y
          :scroll-into-view="item.scrollViewId"
          class="tui-selection-item"
          :style="{ height: height }"
        >
          <view class="tui-first-item" :style="{ height: firstItemTop }"></view>
          <view
            class="tui-selection-cell"
            :style="{ padding: padding, backgroundColor: backgroundColor }"
            :id="`id_${subIndex}`"
            v-for="(subItem, subIndex) in item.list"
            :key="subIndex"
            @tap="change(index, subIndex, subItem)"
          >
            <icon
              type="success_no_circle"
              v-if="item.index === subIndex"
              :color="checkMarkColor"
              :size="checkMarkSize"
              class="tui-icon-success"
            ></icon>
            <image
              :src="subItem.src"
              v-if="subItem.src"
              class="tui-cell-img"
              :style="{ width: imgWidth, height: imgHeight, borderRadius: radius }"
            ></image>
            <view
              class="tui-cell-title"
              :class="{
                'tui-font-bold': item.index === subIndex && textBold,
                'tui-flex-shrink': nowrap,
              }"
              :style="{
                color: item.index === subIndex ? textActiveColor : textColor,
                fontSize: textSize + 'rpx',
              }"
            >
              {{ subItem.text }}
            </view>
            <view
              class="tui-cell-sub_title"
              :style="{ color: subTextColor, fontSize: subTextSize + 'rpx' }"
              v-if="subItem.subText"
            >
              {{ subItem.subText }}
            </view>
          </view>
        </scroll-view>
      </swiper-item>
    </swiper>
  </view>
</template>

<script>
export default {
  name: 'tuiCascadeSelection',
  emits: ['change', 'complete'],
  props: {
    /**
				 * 如果下一级是请求返回，则为第一级数据，否则所有数据
				 * 数据格式
				  [{
					  src: "",
					  text: "",
					  subText: "",
					  value: 0,
					  children:[{
						  text: "",
						  subText: "",
						  value: 0,
						  children:[]
				   }]
				  }]
				 * */
    itemList: {
      type: Array,
      default: () => {
        return [];
      },
    },
    /*
			   初始化默认选中数据
			   [{
				text: "",//选中text
				subText: '',//选中subText
				value: '',//选中value
				src: '', //选中src，没有则传空或不传
				index: 0, //选中数据在当前layer索引
				list: [{src: "", text: "", subText: "", value: 101}] //当前layer下所有数据集合
			  }];

			   */
    defaultItemList: {
      type: Array,
      value: [],
    },
    defaultKey: {
      type: String,
      default: 'text',
    },
    //是否显示header底部细线
    headerLine: {
      type: Boolean,
      default: true,
    },
    //header背景颜色
    headerBgColor: {
      type: String,
      default: '#FFFFFF',
    },
    //顶部标签栏高度
    tabsHeight: {
      type: String,
      default: '88rpx',
    },
    //默认显示文字
    text: {
      type: String,
      default: '请选择',
    },
    //tabs 文字大小
    size: {
      type: Number,
      default: 28,
    },
    //tabs 文字颜色
    color: {
      type: String,
      default: '#555',
    },
    //选中颜色
    activeColor: {
      type: String,
      default: '#5677fc',
    },
    //选中后文字加粗
    bold: {
      type: Boolean,
      default: true,
    },
    //选中后是否显示底部线条
    showLine: {
      type: Boolean,
      default: true,
    },
    //线条颜色
    lineColor: {
      type: String,
      default: '#5677fc',
    },
    //icon 大小
    checkMarkSize: {
      type: Number,
      default: 15,
    },
    //icon 颜色
    checkMarkColor: {
      type: String,
      default: '#5677fc',
    },
    //item 图片宽度
    imgWidth: {
      type: String,
      default: '40rpx',
    },
    //item 图片高度
    imgHeight: {
      type: String,
      default: '40rpx',
    },
    //图片圆角
    radius: {
      type: String,
      default: '50%',
    },
    //item text颜色
    textColor: {
      type: String,
      default: '#333',
    },
    textActiveColor: {
      type: String,
      default: '#333',
    },
    //选中后字体是否加粗
    textBold: {
      type: Boolean,
      default: true,
    },
    //item text字体大小
    textSize: {
      type: Number,
      default: 28,
    },
    //text 是否不换行
    nowrap: {
      type: Boolean,
      default: false,
    },
    //item subText颜色
    subTextColor: {
      type: String,
      default: '#999',
    },
    //item subText字体大小
    subTextSize: {
      type: Number,
      default: 24,
    },
    // item padding
    padding: {
      type: String,
      default: '20rpx 30rpx',
    },
    //占位高度，第一条数据距离顶部距离
    firstItemTop: {
      type: String,
      default: '20rpx',
    },
    //swiper 高度
    height: {
      type: String,
      default: '300px',
    },
    //item  swiper 内容部分背景颜色
    backgroundColor: {
      type: String,
      default: '#FFFFFF',
    },
    //子集数据是否请求返回（默认false，一次性返回所有数据）
    request: {
      type: Boolean,
      default: false,
    },
    //子级数据（当有改变时，默认当前选中项新增子级数据，request=true时生效）
    receiveData: {
      type: Array,
      default: () => {
        return [];
      },
    },
    //改变值则重置数据
    reset: {
      type: [Number, String],
      default: 0,
    },
  },
  watch: {
    itemList(val) {
      this.initData(val, -1);
    },
    receiveData(val) {
      this.subLevelData(val, this.currentTab);
    },
    reset() {
      this.initData(this.itemList, -1);
    },
    defaultItemList(val) {
      this.setDefaultData(val);
    },
  },
  created() {
    this.setDefaultData(this.defaultItemList);
  },
  data() {
    return {
      currentTab: 0,
      //tab栏scrollview滚动的位置
      scrollViewId: 'id__1',
      selectedArr: [],
    };
  },
  methods: {
    setDefaultData(val) {
      let defaultItemList = val || [];
      if (defaultItemList.length > 0) {
        if (
          (typeof defaultItemList[0] === 'string' || typeof defaultItemList[0] === 'number') &&
          !this.request
        ) {
          let subi = -1;
          let selectedArr = [];
          for (let j = 0, len = defaultItemList.length; j < len; j++) {
            let item = defaultItemList[j];
            let list = [];
            let obj = {};
            if (j === 0) {
              list = this.getItemList(-1);
            } else {
              list = this.getItemList(j - 1, subi, selectedArr);
            }
            subi = this.getDefaultIndex(list, item);
            if (subi !== -1) {
              obj = list[subi];
              selectedArr.push({
                text: obj.text || this.text,
                value: obj.value || '',
                src: obj.src || '',
                subText: obj.subText || '',
                index: subi,
                scrollViewId: `id_${subi}`,
                list: list,
              });
            }

            if (subi === -1) break;
          }
          this.selectedArr = selectedArr;
          this.currentTab = selectedArr.length - 1;
          this.$nextTick(() => {
            this.checkCor();
          });
        } else {
          defaultItemList.map((item) => {
            item.scrollViewId = `id_${item.index}`;
          });
          this.selectedArr = defaultItemList;
          this.currentTab = defaultItemList.length - 1;
          this.$nextTick(() => {
            this.checkCor();
          });
        }
      } else {
        this.initData(this.itemList, -1);
      }
    },
    getDefaultIndex(arr, val) {
      if (!arr || arr.length === 0 || val === undefined) return -1;
      let index = -1;
      let key = this.defaultKey || 'text';
      for (let i = 0, len = arr.length; i < len; i++) {
        if (arr[i][key] == val) {
          index = i;
          break;
        }
      }
      return index;
    },
    initData(data, layer) {
      if (!data || data.length === 0) return;
      if (this.request) {
        //第一级数据
        this.subLevelData(data, layer);
      } else {
        let selectedValue = this.selectedValue || {};
        if (selectedValue.type) {
          this.setDefaultData(selectedValue);
        } else {
          this.subLevelData(this.getItemList(layer, -1), layer);
        }
      }
    },
    removeChildren(data) {
      let list = data.map((item) => {
        delete item['children'];
        return item;
      });
      return list;
    },
    getItemList(layer, index, selectedArr) {
      let list = [];
      let arr = JSON.parse(JSON.stringify(this.itemList));
      selectedArr = selectedArr || this.selectedArr;
      if (layer == -1) {
        list = this.removeChildren(arr);
      } else {
        let value = selectedArr[0].index;
        value = value == -1 ? index : value;
        list = arr[value].children || [];
        if (layer > 0) {
          for (let i = 1; i < layer + 1; i++) {
            let val = layer === i ? index : selectedArr[i].index;
            list = list[val].children || [];
            if (list.length === 0) break;
          }
        }
        list = this.removeChildren(list);
      }
      return list;
    },
    //滚动切换
    switchTab: function (e) {
      this.currentTab = e.detail.current;
      this.checkCor();
    },
    //点击标题切换当
    swichNav: function (e) {
      let cur = e.currentTarget.dataset.current;
      if (this.currentTab != cur) {
        this.currentTab = cur;
      }
    },
    checkCor: function () {
      let item = this.selectedArr[this.currentTab];
      item.scrollViewId = 'id__1';
      this.$nextTick(() => {
        setTimeout(() => {
          let val = item.index < 2 ? 0 : Number(item.index - 2);
          item.scrollViewId = `id_${val}`;
        }, 2);
      });

      if (this.currentTab > 1) {
        this.scrollViewId = `id_${this.currentTab - 1}`;
      } else {
        this.scrollViewId = `id_0`;
      }
    },
    change(index, subIndex, subItem) {
      let item = this.selectedArr[index];
      if (item.index == subIndex) return;
      item.index = subIndex;
      item.text = subItem.text;
      item.value = subItem.value;
      item.subText = subItem.subText || '';
      item.src = subItem.src || '';
      this.$emit('change', {
        layer: index,
        subIndex: subIndex, //layer=> Array index
        ...subItem,
      });

      if (!this.request) {
        let data = this.getItemList(index, subIndex);
        this.subLevelData(data, index);
      }
    },
    //新增子级数据时处理
    subLevelData(data, layer) {
      if (!data || data.length === 0) {
        if (layer == -1) return;
        //完成选择
        let arr = this.selectedArr;
        if (layer < arr.length - 1) {
          let newArr = arr.slice(0, layer + 1);
          this.selectedArr = newArr;
        }
        let result = JSON.parse(JSON.stringify(this.selectedArr));
        let lastItem = result[result.length - 1] || {};
        let text = '';
        result.map((item) => {
          text += item.text;
          delete item['list'];
          //delete item['index'];
          delete item['scrollViewId'];
          return item;
        });
        this.$emit('complete', {
          result: result,
          value: lastItem.value,
          text: text,
          subText: lastItem.subText,
          src: lastItem.src,
        });
      } else {
        //重置数据（ >layer层级）
        let item = [
          {
            text: this.text,
            subText: '',
            value: '',
            src: '',
            index: -1,
            scrollViewId: 'id__1',
            list: data,
          },
        ];
        if (layer == -1) {
          this.selectedArr = item;
        } else {
          let retainArr = this.selectedArr.slice(0, layer + 1);
          this.selectedArr = retainArr.concat(item);
        }
        this.$nextTick(() => {
          this.currentTab = this.selectedArr.length - 1;
        });
      }
    },
  },
};
</script>

<style scoped>
.tui-cascade-selection {
  width: 100%;
  box-sizing: border-box;
}

.tui-selection-header {
  width: 100%;
  display: flex;
  align-items: center;
  position: relative;
  box-sizing: border-box;
}

.tui-bottom-line {
  position: relative;
}

.tui-bottom-line::after {
  width: 100%;
  content: '';
  position: absolute;
  border-bottom: 1rpx solid #eaeef1;
  -webkit-transform: scaleY(0.5) translateZ(0);
  transform: scaleY(0.5) translateZ(0);
  transform-origin: 0 100%;
  bottom: 0;
  right: 0;
  left: 0;
}

.tui-btm-none::after {
  border-bottom: 0 !important;
}

.tui-header-item {
  max-width: 240rpx;
  padding: 15rpx 30rpx;
  box-sizing: border-box;
  flex-shrink: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  position: relative;
}

.tui-font-bold {
  font-weight: bold;
}

.tui-active-line {
  width: 60rpx;
  height: 6rpx;
  border-radius: 4rpx;
  position: absolute;
  bottom: 0;
  right: 0;
  left: 50%;
  transform: translateX(-50%);
}

.tui-selection-cell {
  width: 100%;
  box-sizing: border-box;
  display: flex;
  align-items: center;
}

.tui-icon-success {
  margin-right: 12rpx;
}

.tui-cell-img {
  margin-right: 12rpx;
  flex-shrink: 0;
}

.tui-cell-title {
  word-break: break-all;
}

.tui-flex-shrink {
  flex-shrink: 0;
}

.tui-font-bold {
  font-weight: bold;
}

.tui-cell-sub_title {
  margin-left: 20rpx;
  word-break: break-all;
}

.tui-first-item {
  width: 100%;
}
</style>
